#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include <setjmp.h>

void read_png_file(char *filename)
{
    FILE *fp = fopen(filename, "rb");
    if (!fp)
    {
        printf("Error opening PNG file.\n");
        return;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        printf("Error creating PNG read structure.\n");
        fclose(fp);
        return;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        printf("Error creating PNG info structure.\n");
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(fp);
        return;
    }

    png_init_io(png_ptr, fp);
    png_read_info(png_ptr, info_ptr);

    // 获取图像信息
    int width = png_get_image_width(png_ptr, info_ptr);
    int height = png_get_image_height(png_ptr, info_ptr);
    int color_type = png_get_color_type(png_ptr, info_ptr);
    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    // 获取每一行像素的字节数量
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    int pixel_size = rowbytes / width;

    // 读取图像数据
    png_bytepp row_pointers = (png_bytepp)malloc(sizeof(png_bytep) * height);
    png_byte *data = (png_byte *)malloc(rowbytes * height);
    for (int y = 0; y < height; y++)
    {
        row_pointers[y] = data + y * rowbytes;
    }
    png_read_image(png_ptr, row_pointers);

    // 处理图像数据，可以在这里进行各种图像处理操作
    for (int y = 0; y < height; y++)
    {
        png_byte *p = row_pointers[y];
        for (int x = 0; x < width; x++)
        {
            for (int i = 0; i < pixel_size; i++)
            {
                printf("%02X", *(p++));
            }
            printf(" ");
        }
        printf("\n");
    }
    // 释放内存
    free(data);
    free(row_pointers);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
}

void write_png_file(char *filename, int width, int height, int color_type, int bit_depth)
{
    FILE *fp = fopen(filename, "wb");
    if (!fp)
    {
        printf("Error opening PNG file.\n");
        return;
    }

    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        printf("Error creating PNG write structure.\n");
        fclose(fp);
        return;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        printf("Error creating PNG info structure.\n");
        png_destroy_write_struct(&png_ptr, NULL);
        fclose(fp);
        return;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return;
    }

    png_init_io(png_ptr, fp);

    // 设置图像信息
    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    png_write_info(png_ptr, info_ptr);
    // 写入图像数据
    png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height);
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    int pixel_size = rowbytes/width;
    png_byte *data = (png_byte *)malloc(rowbytes * height);
    unsigned char r = 0, g = 80, b = 160;
    for (int y = 0; y < height; y++)
    {
        row_pointers[y] = data + y * rowbytes;
        png_byte *p = row_pointers[y];
        for (int x = 0; x < width; x++)
        {
            *p++ = r++;
            *p++ = g++;
            *p++ = b++;
        }
    }
    png_write_image(png_ptr, row_pointers);

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);

    // 释放内存
    free(data);
    free(row_pointers);
    fclose(fp);
}

int main(int agrc, char **argv)
{
    char filename[32];
    strcpy(filename, "wind.png");

    // 读取PNG文件
    read_png_file(filename);

    // 写入PNG文件
    srand(time_t());
    strcpy(filename, "wind2.png");
    int width = 640;
    int height = 480;
    int color_type = PNG_COLOR_TYPE_RGB;
    int bit_depth = 8;
    write_png_file(filename, width, height, color_type, bit_depth);

    return 0;
}